// File Name: ProviderFragmentCustom.cpp

#include "ProviderFragmentCustom.h"

namespace UIAutomationCPP
{
	ProviderFragmentCustom::ProviderFragmentCustom()
	{
	}

	ProviderFragmentCustom::~ProviderFragmentCustom()
	{
	}

	HRESULT __stdcall ProviderFragmentCustom::GetEmbeddedFragmentRoots(SAFEARRAY** pRetVal)
	{
		return 0;
	}

	HRESULT __stdcall ProviderFragmentCustom::GetRuntimeId(SAFEARRAY ** pRetVal)
	{
		if (pRetVal == NULL) 
		{
			return E_INVALIDARG;
		}
    
		int rId[] = { AppendRuntimeId, itemIndex };
		SAFEARRAY *psa = SafeArrayCreateVector(VT_I4, 0, 2);
		if (psa == NULL)
		{
			return E_OUTOFMEMORY;
		}
    
		for (LONG i = 0; i < 2; i++)
		{
			SafeArrayPutElement(psa, &i, (void*)&(rId[i]));
		}
    
		*pRetVal = psa;
		return S_OK;
	}

	HRESULT __stdcall ProviderFragmentCustom::Navigate(NavigateDirection direction, IRawElementProviderFragment** pRetVal)
	{
		if (pRetVal == NULL) 
		{
			return E_INVALIDARG;
		}

		IRawElementProviderFragment* pFrag = NULL;
		switch(direction)
		{
			case NavigateDirection_Parent:
				pFrag = (IRawElementProviderFragment*)parentProvider;       
				break;
			case NavigateDirection_NextSibling:
				pFrag = (IRawElementProviderFragment*)nextSiblingProvider;
				break;
			case NavigateDirection_PreviousSibling:  
				pFrag = (IRawElementProviderFragment*)previousSiblingProvider;
				break;
		}

		*pRetVal = pFrag;
		if (pFrag != NULL) 
		{
			pFrag->AddRef();
		}

		return S_OK;
	}

	HRESULT __stdcall ProviderFragmentCustom::SetFocus()
	{
		return 0;
	}

	HRESULT __stdcall ProviderFragmentCustom::get_BoundingRectangle(UiaRect* pRetVal)
	{
		if (pRetVal == NULL)
			return E_INVALIDARG;

		UiaRect parentRect;
		HRESULT hr = parentProvider->get_BoundingRectangle(&parentRect);
		pRetVal->left = parentRect.left;
		pRetVal->top = parentRect.top;
		pRetVal->width = parentRect.width;
		pRetVal->height = parentRect.height;

		return S_OK;
	}

	HRESULT __stdcall ProviderFragmentCustom::get_FragmentRoot(IRawElementProviderFragmentRoot** pRetVal)
	{
		if (pRetVal == NULL)
			return E_INVALIDARG;

		IUnknown* pRoot = parentProvider;
		pRoot->AddRef();
		*pRetVal = (IRawElementProviderFragmentRoot*)pRoot;
		return S_OK;
	}

	HRESULT __stdcall ProviderFragmentCustom::QueryInterface(REFIID riid, void **ppvObj)
	{
		if(riid == IID_IUnknown)
			*ppvObj =(IUnknown*)((IRawElementProviderFragment*)this);
		else if(riid == IID_IRawElementProviderFragment)
			*ppvObj =(IRawElementProviderFragment*)this;
		else
		{
			*ppvObj = NULL;
			return E_NOINTERFACE;
		}

		((IUnknown*)(*ppvObj))->AddRef();
		return S_OK;
	}

	ULONG __stdcall ProviderFragmentCustom::AddRef()
	{
		InterlockedIncrement(&refCount);
		return refCount;
	}

	ULONG __stdcall ProviderFragmentCustom::Release()
	{
		ULONG ulRefCount = InterlockedDecrement(&refCount);
		if (ulRefCount == 0)
		{
			delete this;
		}
		return ulRefCount;
	}
}
